﻿
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using ZerAx.Net;
using ZerAx.ObjectNotation;

namespace BlockOS.Server
{
    internal class EntityManager : IServerModule
    {
        private int entityIdCounter = 0;

        private readonly GameServer server;
        private readonly Dictionary<int, EntityData> entities = new();

        private readonly Dictionary<int, int> connIdCheckList = new();
        public EntityManager(GameServer server)
        {
            this.server = server;
            
        }

        public int AddEntity(EntityData entity)
        {
            entities.Add(entityIdCounter, entity);
            return entityIdCounter++;
        }

        public void OnRequestEntities(int connId, Packet packet)
        {   // 反序列化请求包
            var dom = packet.ReadData(Zon.Deserialze).AsCompound();
            
            int playerEId;
            if (!connIdCheckList.ContainsKey(connId))
            {
                playerEId = server.PlayerManager.players[dom.GetString("name")].entityId;
                // 将同步数据写入任务列表
                connIdCheckList[connId] = playerEId;
            }
            else
            {
                playerEId = connIdCheckList[connId];
            }
            // 获取对应的字段
            var pos = dom.GetVec3("pos").Value;
            var rot = dom.GetVec3("rot").Value;
            // 同步客户端的位置数据
            entities[playerEId].SetPosition(pos.x, pos.y, pos.z);
            entities[playerEId].SetRotation(rot.x, rot.y, rot.z);

            server.LogMessage($"Req received from {connId} pos: ({pos.x}, {pos.y}, {pos.z}) rot: ({rot.x}, {rot.y}, {rot.z})");
        }

        public void Update(TimeSpan deltaTime)
        {

        }

        public void Init()
        {

        }

        public void Deinit()
        {

        }

        public void Tick()
        {   
            foreach (var (connId, playerEid) in connIdCheckList)
            {
                var playerEntity = entities[playerEid];
                // 读取玩家实体，然后查询附近的实体
                var nearby = entities
                    .OrderByDescending(
                        e => MathUtil.ManhattanDistance(
                            playerEntity.GetPosition(),
                            e.Value.GetPosition()))
                    .Where(e => e.Key != playerEid)
                    .Take(50)
                    .Select(e => e.Value.ToZon().With("entityId", e.Key));
                // 发送回应报文
                server.SendProtocol(
                    connId,
                    ProtocolId.RESPONSE_ENTITIES,
                    Zon.List(nearby).Serialize);
            }

            connIdCheckList.Clear();
        }
    }
}
